#pragma once

#include "Message.h"

#include "Connector.h"
#include "Interaction.h"
#include "MessageEnd.h"
#include "NamedElement.h"
#include "Namespace.h"
#include "ValueSpecification.h"

namespace uml {

Message::Message(const QString& umlType)
    : NamedElement(umlType) {}

void Message::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    NamedElement::fromJson(json, errorList);
    JsonSerializable::fromJsonArray(arguments_, "arguments", json, errorList);
    connector_ = JsonSerializable::create<Connector>(json.value("connector"), errorList);

    interaction_ = JsonSerializable::create<Interaction>(json.value("interaction"), errorList);

    messageKind_ = (MessageKind)json.value("messageKind").toInt((int)messageKind_);
    messageSort_ = (MessageSort)json.value("messageSort").toInt((int)messageSort_);
    receiveEvent_ = JsonSerializable::create<MessageEnd>(json.value("receiveEvent"), errorList);

    sendEvent_ = JsonSerializable::create<MessageEnd>(json.value("sendEvent"), errorList);

    signature_ = JsonSerializable::create<NamedElement>(json.value("signature"), errorList);

}

void Message::toJson(QJsonObject& json) {
    NamedElement::toJson(json);
    JsonSerializable::toJsonArray(arguments_, "arguments", json);
    if (connector_) {
        QJsonObject connector_json;
        connector_->toJson(connector_json);
        json.insert("connector", connector_json);
    }
    if (interaction_) {
        QJsonObject interaction_json;
        interaction_->toJson(interaction_json);
        json.insert("interaction", interaction_json);
    }
    json.insert("messageKind", (int)messageKind_);
    json.insert("messageSort", (int)messageSort_);
    if (receiveEvent_) {
        QJsonObject receiveEvent_json;
        receiveEvent_->toJson(receiveEvent_json);
        json.insert("receiveEvent", receiveEvent_json);
    }
    if (sendEvent_) {
        QJsonObject sendEvent_json;
        sendEvent_->toJson(sendEvent_json);
        json.insert("sendEvent", sendEvent_json);
    }
    if (signature_) {
        QJsonObject signature_json;
        signature_->toJson(signature_json);
        json.insert("signature", signature_json);
    }
}

/// <summary>
/// isDistinguishableFrom
    /// The query isDistinguishableFrom() specifies that any two Messages may coexist in
    /// the same Namespace, regardless of their names.
/// </summary>
    /// <code>
    /// result = (true)
    /// </code>
bool Message::isDistinguishableFrom(shared_ptr<NamedElement> n, shared_ptr<Namespace> ns) const
{
    return false;
}

/// <summary>
/// arguments getter
/// The arguments of the Message.
/// </summary>
vector<shared_ptr<ValueSpecification>>& Message::arguments() {
    return arguments_;
}

/// <summary>
/// connector getter
/// The Connector on which this Message is sent.
/// </summary>
shared_ptr<Connector> Message::connector() const {
    return connector_;
}

/// <summary>
/// connector setter
/// The Connector on which this Message is sent.
/// </summary>
void Message::setConnector(shared_ptr<Connector> value) {
    connector_ = value;
}

/// <summary>
/// interaction getter
/// The enclosing Interaction owning the Message.
/// </summary>
shared_ptr<Interaction> Message::interaction() const {
    return interaction_;
}

/// <summary>
/// interaction setter
/// The enclosing Interaction owning the Message.
/// </summary>
void Message::setInteraction(shared_ptr<Interaction> value) {
    interaction_ = value;
}

/// <summary>
/// messageKind getter
/// The derived kind of the Message (complete, lost, found, or unknown).
/// </summary>
MessageKind Message::messageKind() const {
    return messageKind_;
}

/// <summary>
/// messageKind setter
/// The derived kind of the Message (complete, lost, found, or unknown).
/// </summary>
void Message::setMessageKind(MessageKind value) {
    messageKind_ = value;
}

/// <summary>
/// messageSort getter
/// The sort of communication reflected by the Message.
/// </summary>
MessageSort Message::messageSort() const {
    return messageSort_;
}

/// <summary>
/// messageSort setter
/// The sort of communication reflected by the Message.
/// </summary>
void Message::setMessageSort(MessageSort value) {
    messageSort_ = value;
}

/// <summary>
/// receiveEvent getter
/// References the Receiving of the Message.
/// </summary>
shared_ptr<MessageEnd> Message::receiveEvent() const {
    return receiveEvent_;
}

/// <summary>
/// receiveEvent setter
/// References the Receiving of the Message.
/// </summary>
void Message::setReceiveEvent(shared_ptr<MessageEnd> value) {
    receiveEvent_ = value;
}

/// <summary>
/// sendEvent getter
/// References the Sending of the Message.
/// </summary>
shared_ptr<MessageEnd> Message::sendEvent() const {
    return sendEvent_;
}

/// <summary>
/// sendEvent setter
/// References the Sending of the Message.
/// </summary>
void Message::setSendEvent(shared_ptr<MessageEnd> value) {
    sendEvent_ = value;
}

/// <summary>
/// signature getter
/// The signature of the Message is the specification of its content. It refers
/// either an Operation or a Signal.
/// </summary>
shared_ptr<NamedElement> Message::signature() const {
    return signature_;
}

/// <summary>
/// signature setter
/// The signature of the Message is the specification of its content. It refers
/// either an Operation or a Signal.
/// </summary>
void Message::setSignature(shared_ptr<NamedElement> value) {
    signature_ = value;
}

} // namespace uml
